package com.simba.server.commands.impl.web;

import java.util.*;

import com.google.gson.Gson;
import com.simba.common.command.ICommand;
import com.simba.server.base.TimeUtil;
import com.simba.server.components.MachineParams;
import com.simba.server.components.data.ResultInfo;
import com.simba.server.components.data.ResultSlot;
import org.apache.log4j.Logger;

import com.simba.common.log.LogUtil;
import com.simba.server.ServerParam;
import com.simba.server.base.CommonUtil;
import com.simba.server.components.SortCommonDefines;
import com.simba.server.components.data.SortInfo;
import com.simba.server.webservice.WebServiceManager;

/**
 * 请求物理格口
 *
 * @return success or error
 */
public class WebSortInfoCmd implements ICommand
{
	public static final String NAME = "WebSortInfoCmd";
	private static final Logger logger = Logger.getLogger(WebSortInfoCmd.class);
	private final SortInfo sortInfo;

	public WebSortInfoCmd(SortInfo sortInfo)
	{
		this.sortInfo = sortInfo;
	}

	@Override
	public String getName()
	{
		return WebSortInfoCmd.NAME;
	}

	@Override
	public Boolean run(Object params)
	{
		boolean ret = false;
		String remoteMethod = "AutoSort/Sort";

		Map<String,Object> rp = new HashMap<>();
		//自动生成
		rp.put("Guid", this.sortInfo.getSortingId());
		//一个面单上扫描出来的单号集合（可能会存在一个面单贴多个条码的情况）
		rp.put("Barcodes", new String[]{CommonUtil.doNullData(this.sortInfo.getBarcode().trim(), "0000000000000")});
		//分拣机代码
		rp.put("MachineCode", MachineParams.getInstance().getDeviceId());
		//重量 单位(g) 参考值1
		rp.put("Weight",CommonUtil.doNullData(this.sortInfo.getWeight(),"1"));
		//供包台号，可写死为1
		rp.put("PlatId",CommonUtil.doNullData(this.sortInfo.getSorterId(),"1"));
		//扫描头编号，可写死为1
//		rp.put("Obr",this.sortInfo.getObr());
		rp.put("Obr",1);
		//长，单位mm  参考值1
		rp.put("Length",CommonUtil.doNullData(this.sortInfo.getLength(),"1"));
		//宽，单位mm  参考值1
		rp.put("Width",CommonUtil.doNullData(this.sortInfo.getWidth(),"1"));
		//高，单位mm  参考值1
		rp.put("Height",CommonUtil.doNullData(this.sortInfo.getHeight(),"1"));
		//请求时间
		rp.put("RequestTime", TimeUtil.getTimeDateString("yyyy-MM-dd HH:mm:ss", new Date()));
		//员工工号
		rp.put("StCode", "admin");
		//分拣人id
		rp.put("CreaterId", "1");
		//分拣人组织机构id
		rp.put("CreateOGID", "1");
		//分拣人组织机构代码
		rp.put("CreateOGCode", "1");

		Gson gson = CommonUtil.getGson();
		String content = gson.toJson(rp);
		try
		{
			ResultInfo response = WebServiceManager.getInstance().doHttpServiceByPost(
					ServerParam.REMOTE_WEBSERVICE_ADDRESS, remoteMethod, content);
			if (response != null && response.getCode() >= 200 && response.getCode() < 202)
			{
				ret = this.handleSortInfoResponse(response);
			}
			else
			{
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_9_POST_INTER_ERROR);
			}
		}
		catch (Exception ex)
		{
			LogUtil.LogError(WebSortInfoCmd.logger,
					"get factualSlot by sortInfo error: " + ex.getMessage());
			this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_9_POST_INTER_ERROR);
			ret = false;
		}

		return ret;
	}

	private void doFailedResult(ResultSlot data)
	{
		if (data == null){
			this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_12_POST_UNKNOWN_ERROR);
			this.sortInfo.getSlotsList().clear();
			return;
		}

		switch (data.getCode())
		{
			case 200:
				// 0 成功
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_0_SUCCESS);
				this.sortInfo.getSlotsList().clear();
				break;
			case 400:
				// 未知错误
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_12_POST_UNKNOWN_ERROR);
				this.sortInfo.getSlotsList().clear();
				break;
			case 401:
				// 请求包裹号没有运单信息
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_1_NO_SORT_INFO);
				this.sortInfo.getSlotsList().clear();
				break;
			case 402:
				// 请求包裹号对应站点没有对应的分拣计划
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_2_NO_SORT_PLAN);
				this.sortInfo.getSlotsList().clear();
				break;
			case 403:
				//格口容量已满(格口容量满的情况下，需要向plc发送格口闪灯情况提示)
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_10_POST_OTHER_ERROR);
				this.sortInfo.getSlotsList().clear();
				break;
			case 405:
				//格口已锁
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_10_POST_OTHER_ERROR);
				this.sortInfo.getSlotsList().clear();
				break;
			case 406:
				//没有创建格口批次
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_10_POST_OTHER_ERROR);
				this.sortInfo.getSlotsList().clear();
				break;
			case 500:
				//云途服务器内部异常
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_10_POST_OTHER_ERROR);
				this.sortInfo.getSlotsList().clear();
				break;
			case 10000:
				//请求参数有误
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_10_POST_OTHER_ERROR);
				this.sortInfo.getSlotsList().clear();
				break;
			default:
				this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_12_POST_UNKNOWN_ERROR);
				this.sortInfo.getSlotsList().clear();
				break;
		}
	}

	private void doSuccessResult(ResultSlot data){
		if (data!=null){
			List<Integer> physicalSlots = this.parseSlot(data.getChuteCode());

			for (Integer slot : physicalSlots)
			{
				if (slot > 0 && slot <= MachineParams.getInstance().getSlotNum())
				{
					this.sortInfo.getSlotsList().add(slot);
				}
			}
		}

		if (this.sortInfo.getSlotsList().isEmpty())
		{
			this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_11_POST_FAIL_SLOT_ERROR);
		}
	}

	private boolean handleSortInfoResponse(ResultInfo response)
	{
		boolean ret;

		if (this.sortInfo == null)
		{
			LogUtil.LogError(WebSortInfoCmd.logger, "request sort info error: parse sort info data is null");
			return false;
		}

		try
		{
			ResultSlot resultSlot = CommonUtil.getGson().fromJson(response.getData(), ResultSlot.class);
			if (resultSlot.getCode()==200){
				this.doSuccessResult(resultSlot);
				ret = true;
			}else {
				this.doFailedResult(resultSlot);
				ret = false;
			}
		}
		catch (Exception e)
		{
			ret = false;
			this.sortInfo.setErrorCodeSVR(SortCommonDefines.ERROR_CODE_13_POST_PARAMS_ERROR);
			LogUtil.LogError(WebSortInfoCmd.logger, "parse request sort info result failed : " + e);
		}

		return ret;
	}

	private List<Integer> parseSlot(List<String> slots)
	{
		List<Integer> physicalSlots = new LinkedList<>();
		try
		{
			if (slots == null || slots.isEmpty())
			{
				physicalSlots.add(0);
			}
			else
			{
				for (String slot : slots) {
					physicalSlots.add(Integer.parseInt(slot));
				}
			}
		}
		catch (Exception e)
		{
			LogUtil.LogError(WebSortInfoCmd.logger,
					"Parse Slot Error! slots:" + slots + ", message" + e.getMessage());
		}

		return physicalSlots;
	}

}
